﻿using System.Text;
using EmbeddedSharp.Core;

namespace Zove.Runtime.Core
{
    /// <summary>
    /// Enhanced C# trnaslator
    /// </summary>
    public class EnhancedCSharpCodeTranslator : CSharpCodeTranslator
    {
        protected string Prefix = string.Empty;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="funMgr"></param>
        /// <param name="prefix"></param>
        public EnhancedCSharpCodeTranslator(
            IFunctionManager funMgr, string prefix)
            : base(funMgr)
        {
            Prefix = prefix;
        }

        /// <summary>
        /// Add prefix
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public override object Visit(IdentifierNode node)
        {
            return string.IsNullOrEmpty(Prefix)
                       ? node.Value
                       : Prefix + "." + node.Value;
        }

        /// <summary>
        /// Check if the function is a CLR built in function
        /// </summary>
        /// <param name="funcName"></param>
        /// <returns></returns>
        public static bool IsClrShipped(string funcName)
        {
            var funcNames = new[]
                                {
                                    "abs", "sin", "cos",
                                    "tan", "asin", "acos",
                                    "atan", "cosh", "sinh", "tanh"
                                };
            foreach (string f in funcNames)
            {
                if (f == funcName)
                {
                    return true;
                }
            }

            return false;
        }

        public override object Visit(FuncNode node)
        {
            string name;

            if (IsClrShipped(node.Value))
            {
                name = "Math."
                       + char.ToUpper(node.Value[0])
                       + node.Value.Substring(
                           1, node.Value.Length - 1).ToLower();
            }
            else
            {
                name = node.Value;
            }

            var buff = new StringBuilder();

            buff.Append(name).Append("(");
            for (int index = 0;
                 index < node.Parameters.Count;
                 index++)
            {
                object value = node.Parameters[index].Accept(this);
                buff.Append(value.ToString());
                if (index + 1 < node.Parameters.Count)
                {
                    buff.Append(",");
                }
            }
            buff.Append(")");

            return buff.ToString();
        }
    }
}